chat: migrate supported workspace MCP servers - #333286
chat: migrate supported workspace MCP servers#333286Vritant Bhardwaj (vritant24) wants to merge 9 commits into
Conversation
Offer per-server migration from .vscode/mcp.json into the workspace-root .mcp.json for Agent Host harnesses. Preserve behavior by limiting candidates to configurations the destination can represent and guard cross-file updates against conflicts and concurrent changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
Review tier: Balanced
Findings: 2
New issues introduced by this change (5)
| Severity | Finding |
|---|---|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigration.ts — The existing destination entry is compared in raw JSON form while the candidate is canonicalized.… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigrationServiceImpl.ts — A stale support snapshot can still reference a source file that has just been deleted or become… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts — Unlike the existing file-migration path, this call omits the error callback, so permission errors,… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts — In a multi-root workspace, different folders can contain MCP servers with the same name, but both… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigration.ts — The optimistic metadata does not reject concurrent deletion of a file that existed at read time.… |
What changed in this PR
Adds migration of supported workspace MCP servers from .vscode/mcp.json to Agent Host–native root .mcp.json files.
Changes:
- Discovers and validates per-server migration candidates.
- Adds guarded migration, conflict handling, and rollback logic.
- Integrates MCP migration into the customization UI with tests.
| File | Description |
|---|---|
aiCustomizationManagementEditor.fixture.ts |
Supplies the migration service with a file service. |
mcpServerMigration.test.ts |
Tests migration safety and conflict handling. |
customizationMigrationServiceImpl.test.ts |
Tests MCP candidate discovery. |
customizationMigration.test.ts |
Tests MCP migration messaging. |
aiCustomizationManagementEditor.test.ts |
Tests selection, rendering, and refresh behavior. |
agentHostMcpServerSupport.test.ts |
Tests exclusion of explicit working directories. |
customizationMigrationService.ts |
Defines MCP migration candidate contracts. |
customizationMigrationServiceImpl.ts |
Computes eligible MCP migration candidates. |
customizationMigrationCategories.ts |
Adds the MCP migration category and copy. |
customizationMigration.ts |
Implements MCP file migration transactions. |
aiCustomizationManagementEditor.ts |
Integrates MCP migration into the editor UI. |
agentHostMcpServerSupport.ts |
Exposes persistable MCP configurations. |
AI_CUSTOMIZATIONS.md |
Documents the expanded migration contract. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ile existence checks
Revalidate migration candidates against source files, preserve errors and selection state across refreshes, and guard MCP file updates against conflicts and deletion races. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Screenshot ChangesBase: Changed (2)2 insignificant change(s) omitted (≤20 px, Δ≤2). See CI logs for details. blocks-ci screenshots changedReplace the contents of Updated blocks-ci-screenshots.md<!-- auto-generated by CI — do not edit manually -->
#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentHostPromptMigration/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentHostPromptMigration/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentsTab/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentsTab/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentsTabNarrow/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/AgentsTabNarrow/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/EmbeddedMcpDetailUninstalled/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/EmbeddedMcpDetailUninstalled/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/HooksEmptyWorkspace/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/HooksEmptyWorkspace/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/McpServerDetailNarrow/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/McpServerDetailNarrow/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/McpServersTab/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/McpServersTab/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogHome/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogHome/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogHomeNarrow/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogHomeNarrow/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogSearch/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginCatalogSearch/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginDetail/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginDetail/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginsTab/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginsTab/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginsTabNarrow/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PluginsTabNarrow/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/PromptMigration/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/PromptMigration/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/ToolsTab/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/ToolsTab/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/UserDataMigration/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/UserDataMigration/Light

#### chat/aiCustomizations/aiCustomizationManagementEditor/WelcomePage/Dark

#### chat/aiCustomizations/aiCustomizationManagementEditor/WelcomePage/Light

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/AllAccessoriesFacing/Dark

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/AllAccessoriesFacing/Light

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/AllRuntimeStates/Dark

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/AllRuntimeStates/Light

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/CoveredAntennaeComparison/Dark

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/CoveredAntennaeComparison/Light

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/CriticalPoses/Dark

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/CriticalPoses/Light

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/LiveEyeLayering/Dark

#### chat/chatPetAccessoryRig/chatPetAccessoryRig/LiveEyeLayering/Light

#### chat/petAchievements/standaloneModal/chatPetAchievementsEditor/MixedSelected/Dark

#### chat/petAchievements/standaloneModal/chatPetAchievementsEditor/MixedSelected/Light

#### editor/codeEditor/CodeEditor/Dark

#### editor/codeEditor/CodeEditor/Light

#### editor/injectedTextDecorations/ColorDecorators/Dark

#### editor/injectedTextDecorations/ColorDecorators/Light

#### editor/injectedTextDecorations/InlayHints/Dark

#### editor/injectedTextDecorations/InlayHints/Light

#### editor/injectedTextDecorations/InlineProgress/Dark

#### editor/injectedTextDecorations/InlineProgress/Light

#### editor/injectedTextDecorations/SelectedColorDecorator/Dark

#### editor/injectedTextDecorations/SelectedColorDecorator/Light

#### editor/inlineChatZoneWidget/InlineChatZoneWidget/Dark

#### editor/inlineChatZoneWidget/InlineChatZoneWidget/Light

#### editor/inlineChatZoneWidget/InlineChatZoneWidgetTerminated/Dark

#### editor/inlineChatZoneWidget/InlineChatZoneWidgetTerminated/Light

#### sessions/accountMenu/petAchievementBadges/chatPetAchievementBadges/AllBadges/Dark

#### sessions/accountMenu/petAchievementBadges/chatPetAchievementBadges/AllBadges/Light

#### sessions/chat/newWidget/newChatWidget/NewSessionAttachedContext/Dark

#### sessions/chat/newWidget/newChatWidget/NewSessionAttachedContext/Light

#### sessions/chat/newWidget/newChatWidget/NewSessionGitHubContextPicker/Dark

#### sessions/chat/newWidget/newChatWidget/NewSessionGitHubContextPicker/Light

#### sessions/chat/newWidget/newChatWidget/NewSessionRemoteWorkspace/Dark

#### sessions/chat/newWidget/newChatWidget/NewSessionRemoteWorkspace/Light

#### sessions/chat/newWidget/newChatWidget/NewSessionWorkspacePicker/Dark

#### sessions/chat/newWidget/newChatWidget/NewSessionWorkspacePicker/Light

#### sessions/sessionsList/SessionsList_NarrowHoverToolbar/Dark

#### sessions/sessionsList/SessionsList_NarrowHoverToolbar/Light

#### sessions/sessionsList/SessionsList_NestedChatHierarchyGuides/Dark

#### sessions/sessionsList/SessionsList_NestedChatHierarchyGuides/Light

#### sessions/sessionsList/SessionsList_PeerChatInProgress/Dark

#### sessions/sessionsList/SessionsList_PeerChatInProgress/Light
Patch--- test/componentFixtures/blocks-ci-screenshots.md 2026-09-02 17:50:23.529331787 +0000
+++ /tmp/blocks-ci-updated.md 2026-09-02 18:00:07.629992604 +0000
@@ -91,10 +91,10 @@

#### chat/aiCustomizations/aiCustomizationManagementEditor/UserDataMigration/Dark
-
+
#### chat/aiCustomizations/aiCustomizationManagementEditor/UserDataMigration/Light
-
+
#### chat/aiCustomizations/aiCustomizationManagementEditor/WelcomePage/Dark
 |
Use the provisional session's creation roots until the Agent Host session snapshot arrives so first-request migration hints assess the correct scope. Confirmed session state remains authoritative once hydrated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ted-mcp-servers # Conflicts: # src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts # src/vs/workbench/contrib/chat/test/browser/aiCustomization/aiCustomizationManagementEditor.test.ts
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Candidate identity and overlapping refresh races can migrate an unintended server or leave migration state stale.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Balanced
Findings: 2
New issues introduced by this change (3)
| Severity | Finding |
|---|---|
src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts — The MCP selection key omits the source URI. Workspace-folder server IDs are based on the folder's… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigrationServiceImpl.ts — Revalidation replaces the selected snapshots with freshly planned candidates. A still-eligible… |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigrationModel.ts — A newer refresh invalidates this result even when it refreshes a disjoint category. Partial… |
Issues resolved since last review (5)
| Severity | Finding |
|---|---|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigration.ts — The optimistic metadata does not reject concurrent deletion of a file that existed at read time.… View resolved comment |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts — In a multi-root workspace, different folders can contain MCP servers with the same name, but both… View resolved comment |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/aiCustomizationManagementEditor.ts — Unlike the existing file-migration path, this call omits the error callback, so permission errors,… View resolved comment |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigrationServiceImpl.ts — A stale support snapshot can still reference a source file that has just been deleted or become… View resolved comment |
|
src/vs/workbench/contrib/chat/browser/aiCustomization/customizationMigration.ts — The existing destination entry is compared in raw JSON form while the candidate is canonicalized.… View resolved comment |
| return isMcpServerCustomizationMigrationCandidate(customization) | ||
| ? `mcp:${customization.id}` | ||
| : `file:${customization.uri.toString()}:${customization.storage}`; |
| async migrateMcpServers(sessionResource: URI, requestedCandidates: readonly IMcpServerCustomizationMigrationCandidate[]): Promise<IMcpServerMigrationResult> { | ||
| const currentMigration = await this.computeMigration(sessionResource, CustomizationMigrationType.McpServers); | ||
| const requestedIds = new Set(requestedCandidates.map(candidate => candidate.id)); | ||
| const currentCandidates = currentMigration.candidates.filter(candidate => requestedIds.has(candidate.id)); |
| if (!this.isCurrent(refreshSequence, activeHarnessId, activeSessionResource)) { | ||
| return; |
Tie selection and execution to source-aware candidate identities, and serialize coalesced refreshes so category state cannot become stale. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ary spread operators


Summary
.vscode/mcp.jsonfiles..mcp.jsonconsumed directly by Agent Host harnesses.Technical context for AI-assisted review
Intent and previous behavior
Agent Host support reporting can distinguish MCP configurations it can consume from configurations whose source or shape is unsupported. Supported workspace-folder servers were forwarded through the client because Agent Host discovers root
.mcp.jsonfiles but not.vscode/mcp.json. The customizations experience reported compatibility but offered no way to move those servers into the runtime-native location.Implementation
The customization migration service now projects eligible workspace-folder servers as individual migration candidates. Candidate discovery uses the active session's working-directory scope, current MCP enablement, support assessment, and the original source entry. Only configurations whose source and projected destination forms are equivalent are offered, excluding unresolved variables and destination-incompatible behavior.
MCP is registered as a separate migration category alongside prompt-file and user-data migrations. The shared migration page provides per-server selection, source and target paths, confirmation, completion feedback, and live refresh when the MCP inventory or active session roots change.
The file transaction merges selected entries into strict
{ "mcpServers": { ... } }JSON at each workspace root and removes only those entries from.vscode/mcp.json. Existing equivalent entries are deduplicated; conflicting entries are left untouched. Reads and writes retain file metadata for optimistic concurrency checks, and the destination is verified after the source update so a concurrent destination change restores the source entry.Behavior and constraints
.vscode/mcp.jsonservers..mcp.jsonfiles must use strict JSON and the supportedmcpServerswrapper.Review context
The main review boundary is data safety across two independently editable configuration files. Candidate eligibility is recomputed after confirmation, source contents are revalidated before deletion, writes use optimistic concurrency metadata, and post-write verification avoids reporting success when the destination changed concurrently.